<template>
  <div class="app">
    <div class="controls">
      <input 
        v-model="searchQuery" 
        placeholder="搜索节点..." 
        class="search-input" 
      />
    </div>

    <div class="graph-wrapper">
      <div ref="graphContainer" class="graph-container"></div>
      <div v-if="debug" class="debug-info">
        <p>Nodes: {{ nodes.length }}</p>
        <p>Edges: {{ edges.length }}</p>
      </div>
    </div>

    <div v-if="selectedNode" class="node-detail">
      <h3>{{ selectedNode.label }}</h3>
      <p v-if="selectedNode.group">类型: {{ selectedNode.group }}</p>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, onBeforeUnmount, watch } from 'vue';
import { Network } from 'vis-network';
import { DataSet } from 'vis-data';

interface Node {
  id: number;
  label: string;
  group?: string;
  hidden?: boolean;
}

interface Edge {
  id?: string;
  from: number;
  to: number;
  label?: string;
}

// Initial data
const initialNodes: Node[] = [
  // 领域
  { id: 1, label: '人工智能', group: '领域' },
  { id: 10, label: '数据科学', group: '领域' },
  
  // 技术
  { id: 2, label: '机器学习', group: '技术' },
  { id: 3, label: '深度学习', group: '技术' },
  { id: 4, label: '自然语言处理', group: '技术' },
  { id: 5, label: '计算机视觉', group: '技术' },
  { id: 6, label: '强化学习', group: '技术' },
  { id: 7, label: '知识图谱', group: '技术' },
  
  // 应用
  { id: 8, label: '智能客服', group: '应用' },
  { id: 9, label: '自动驾驶', group: '应用' },
  { id: 11, label: '推荐系统', group: '应用' },
  { id: 12, label: '医疗影像分析', group: '应用' },
  
  // 算法
  { id: 13, label: '卷积神经网络', group: '算法'},
  { id: 14, label: 'Transformer', group: '算法' },
  { id: 15, label: '随机森林', group: '算法' },
  
  // 机构
  { id: 16, label: 'Google Research', group: '机构'},
  { id: 17, label: 'OpenAI', group: '机构' },
  { id: 18, label: '斯坦福大学', group: '机构' },
  
  // 人物
  { id: 19, label: 'Yann LeCun', group: '人物'},
  { id: 20, label: 'Geoffrey Hinton', group: '人物' },
  { id: 21, label: '李飞飞', group: '人物' }
];

const initialEdges: Edge[] = [
  // 技术关系
  { from: 2, to: 1, label: '属于' },   // 机器学习 → 人工智能
  { from: 3, to: 2, label: '子类' },   // 深度学习 → 机器学习
  { from: 4, to: 1, label: '应用' },   // NLP → 人工智能
  { from: 5, to: 1, label: '应用' },   // CV → 人工智能
  { from: 6, to: 2, label: '子类' },   // 强化学习 → 机器学习
  { from: 7, to: 1, label: '支撑技术' },// 知识图谱 → 人工智能
  
  // 应用关系
  { from: 8, to: 4, label: '基于' },    // 智能客服 → NLP
  { from: 9, to: 5, label: '基于' },    // 自动驾驶 → CV
  { from: 11, to: 2, label: '基于' },   // 推荐系统 → 机器学习
  { from: 12, to: 5, label: '基于' },   // 医疗影像 → CV
  
  // 算法关联
  { from: 13, to: 3, label: '核心算法' }, // CNN → 深度学习
  { from: 14, to: 4, label: '核心算法' }, // Transformer → NLP
  { from: 15, to: 2, label: '基础算法' }, // 随机森林 → 机器学习
  
  // 机构关系
  { from: 16, to: 3, label: '重点研究' }, // Google → 深度学习
  { from: 17, to: 14, label: '开发' },   // OpenAI → Transformer
  { from: 18, to: 5, label: '领先研究' }, // 斯坦福 → CV
  
  // 人物关系
  { from: 19, to: 13, label: '提出' },   // Yann LeCun → CNN
  { from: 20, to: 3, label: '推动发展' }, // Hinton → 深度学习
  { from: 21, to: 5, label: '领导研究' }, // 李飞飞 → CV
  { from: 19, to: 16, label: '任职' },  // Yann LeCun → Google
  { from: 21, to: 18, label: '任职' }    // 李飞飞 → 斯坦福
];

// Debug flag
const debug = ref(true);

// Reactive data
const nodes = new DataSet<Node>(initialNodes);
const edges = new DataSet<Edge>(initialEdges);
const network = ref<Network | null>(null);
const graphContainer = ref<HTMLElement | null>(null);
const selectedNode = ref<Node | null>(null);
const searchQuery = ref('');

// Computed property for filtered nodes
const filteredNodes = computed(() => {
  if (!searchQuery.value) return nodes.get();
  const filtered = nodes.get().filter(node =>
    node.label.toLowerCase().includes(searchQuery.value.toLowerCase())
  );
  return filtered;
});

// Watch for filtered nodes changes
const updateVisibleNodes = () => {
  if (network.value) {
    const nodeIds = filteredNodes.value.map(node => node.id);
    nodes.update(
      nodes.get().map(node => ({
        ...node,
        hidden: !nodeIds.includes(node.id)
      }))
    );
  }
};

// Configuration options
const options = {
  nodes: {
    shape: 'box',
    font: { 
      size: 16,
      color: '#333',
    },
    color: {
      background: '#F5F5F5',
      border: '#4ECDC4',
      highlight: { 
        background: '#FF6B6B',
        border: '#FF6B6B',
      },
    },
    borderWidth: 2,
    shadow: true,
  },
  edges: {
    arrows: 'to',
    smooth: true,
    color: '#666',
    width: 2,
  },
  interaction: { 
    hover: true,
    navigationButtons: true,
    keyboard: true,
  },
  physics: {
    enabled: true,
    stabilization: {
      enabled: true,
      iterations: 100,
      fit: true,
    },
  },
};

// Initialize graph
onMounted(() => {
  if (graphContainer.value) {
    console.log('Initializing network with:', {
      nodes: initialNodes,
      edges: initialEdges,
    });

    network.value = new Network(
      graphContainer.value,
      { nodes, edges },
      options
    );

    // Bind events
    network.value.on('click', handleNodeClick);
    network.value.on('stabilizationProgress', function(params) {
      console.log('Stabilization progress:', params.iterations, '/', params.total);
    });
    network.value.on('stabilizationIterationsDone', function() {
      console.log('Stabilization finished');
    });
  }
});

// Destroy instance
onBeforeUnmount(() => {
  if (network.value) {
    network.value.destroy();
  }
});

// Click node event
const handleNodeClick = (event: any) => {
  if (event.nodes.length) {
    const nodeId = event.nodes[0];
    const nodeData = nodes.get(nodeId);
    if (nodeData && typeof nodeData === 'object' && 'id' in nodeData && 'label' in nodeData) {
      console.log('Node clicked:', nodeData);
      selectedNode.value = nodeData as Node;
    }
  }
};

// Watch for search query changes
watch(searchQuery, () => {
  updateVisibleNodes();
});

// Expose methods (for parent component)
defineExpose({
  updateData: (newNodes: Node[], newEdges: Edge[]) => {
    const edgesWithIds = newEdges.map((edge, index) => ({
      ...edge,
      id: edge.id || `e${index}`
    }));
    nodes.update(newNodes);
    edges.update(edgesWithIds);
  },
});
</script>

<style scoped>
.app {
  padding: 20px;
  max-width: 1200px;
  margin: 0 auto;
  min-height: 100vh;
  background-color: #fff;
}

.title {
  font-size: 24px;
  color: #2c3e50;
  margin-bottom: 20px;
  text-align: center;
}

.controls {
  margin-bottom: 20px;
  display: flex;
  justify-content: center;
}

.search-input {
  width: 300px;
  padding: 8px 12px;
  font-size: 14px;
  border: 1px solid #ddd;
  border-radius: 4px;
  outline: none;
}

.search-input:focus {
  border-color: #4ECDC4;
  box-shadow: 0 0 0 2px rgba(78, 205, 196, 0.2);
}

.graph-wrapper {
  position: relative;
  width: 100%;
  height: 600px;
  background-color: #ffffff;
  border-radius: 4px;
  overflow: hidden;
  border: 1px solid #eee;
  margin: 20px 0;
}

.graph-container {
  width: 100%;
  height: 100%;
}

.debug-info {
  position: absolute;
  top: 10px;
  right: 10px;
  background: rgba(255, 255, 255, 0.9);
  padding: 10px;
  border-radius: 4px;
  border: 1px solid #eee;
  font-size: 12px;
  z-index: 1000;
}

.debug-info p {
  margin: 5px 0;
  color: #666;
}

.node-detail {
  margin-top: 20px;
  padding: 15px;
  background: #f8f9fa;
  border-radius: 4px;
  border: 1px solid #e9ecef;
}

.node-detail h3 {
  margin: 0 0 10px 0;
  color: #2c3e50;
}

.node-detail p {
  margin: 5px 0;
  color: #666;
}
</style>

<script lang="ts">
export default {
  name: 'KnowledgeGraph'
};
</script> 